package com.shen.rw;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    public static void main(String[] args) {
        //MyCache myCache=new MyCache();
        MyCache2 myCache=new MyCache2();

        for (int i = 1; i <=10; i++) {
            final  int temp=i;
            new Thread(()->{
                myCache.set(temp+"",temp);
            },String.valueOf(i)).start();
        }

        for (int i = 1; i <= 10; i++) {
            final  int temp=i;
            new Thread(()->{
                myCache.get(temp+"");
            },String.valueOf(i)).start();
        }

    }
}

/**
 * 自定义一个缓存
 */
class  MyCache{
    private volatile Map<String,Object> map=new HashMap<>();

    //写
    public void set(String key,Object value){
        System.out.println(Thread.currentThread().getName()+"写入"+key);
        map.put(key,value);
        System.out.println(Thread.currentThread().getName()+"写入成功！");
    }

    //读
    public void get(String key){
        System.out.println(Thread.currentThread().getName()+"读取"+key);
        Object o = map.get(key);
        System.out.println(Thread.currentThread().getName()+"读取成功！");
    }

    /**
     * 2写入2
     * 2写入成功！
     * 1写入1
     * 1写入成功！
     * 4写入4
     * 4写入成功！
     * 3写入3     //这里就出现了并发问题  本应该是3写入3 3写入成功！ 但6号线程又插队过来，写入6号线程的数据
     * 6写入6
     * 6写入成功！
     * 5写入5
     * 5写入成功！
     * 3写入成功！
     */
}


/**
 * 自定义一个缓存   加读写锁
 *
 * 读-读  可以共存
 * 读-写  不可以共存
 * 写-写  不能共存
 *
 * 独占线程（写锁） 一次只能被一个线程占有
 * 共享锁（读锁） 多个线程可同时占有
 */
class  MyCache2{
    private volatile Map<String,Object> map=new HashMap<>();
    //读写锁，写只给一个线程，读可以给所有线程读
    ReadWriteLock readWriteLock=new ReentrantReadWriteLock();

    //写
    public void set(String key,Object value){
        readWriteLock.writeLock().lock();//上锁

        try {
            System.out.println(Thread.currentThread().getName()+"写入"+key);
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"写入成功！");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.writeLock().unlock();//解锁
        }

    }

    //读
    public void get(String key){
        readWriteLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName()+"读取"+key);
            Object o = map.get(key);
            System.out.println(Thread.currentThread().getName()+"读取成功！");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readWriteLock.readLock().unlock();
        }

    }

    /**
     * 1写入1
     * 1写入成功！
     * 2写入2
     * 2写入成功！
     * 3写入3
     * 3写入成功！
     * 4写入4
     * 4写入成功！
     * 5写入5
     * 5写入成功！
     * 6写入6
     * 6写入成功！
     * 7写入7
     * 7写入成功！
     * 8写入8
     * 8写入成功！
     * 9写入9
     * 9写入成功！
     * 10写入10
     * 10写入成功！
     * 2读取2
     * 2读取成功！
     * 5读取5
     * 5读取成功！
     * 4读取4
     * 4读取成功！
     * 8读取8
     * 8读取成功！
     * 9读取9
     * 9读取成功！
     * 10读取10
     * 10读取成功！
     * 1读取1
     * 1读取成功！
     * 7读取7
     * 7读取成功！
     * 3读取3
     * 3读取成功！
     * 6读取6
     * 6读取成功！
     */
}
